/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 北京银杉金服科技有限公司
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2018/9/9 20:34
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.service.impl;

import com.hyacinth.constant.ErrorCodeEnum;
import com.hyacinth.constant.IDict;
import com.hyacinth.constant.ResourceTypeEnum;
import com.hyacinth.constant.Symbol;
import com.hyacinth.dto.ResourceDto;
import com.hyacinth.entity.Resource;
import com.hyacinth.entity.Role;
import com.hyacinth.exception.BusinessException;
import com.hyacinth.repository.jpa.ResourceRepository;
import com.hyacinth.repository.jpa.ResourceRoleRepository;
import com.hyacinth.repository.jpa.UserRoleRepository;
import com.hyacinth.service.ResourceService;
import com.hyacinth.util.BeanUtils;
import com.hyacinth.util.JsonMapper;
import com.hyacinth.util.XaUtils;
import com.hyacinth.util.model.PageBean;
import com.hyacinth.util.model.PageBeanFactory;
import com.hyacinth.util.support.DynamicSpecifications;
import com.hyacinth.util.support.SearchFilter;
import com.hyacinth.vo.ResourceVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
@Slf4j
@Service
@Transactional
public class ResourceServiceImpl implements ResourceService {

    private final ResourceRepository resourceRepository;
    private final UserRoleRepository userRoleRepository;
    private final ResourceRoleRepository resourceRoleRepository;

    @Autowired
    public ResourceServiceImpl(UserRoleRepository userRoleRepository,
                               ResourceRepository resourceRepository,
                               ResourceRoleRepository resourceRoleRepository) {
        this.resourceRoleRepository = resourceRoleRepository;
        this.userRoleRepository = userRoleRepository;
        this.resourceRepository = resourceRepository;
    }

    @Override
    public List<Resource> findBanRes() {
        return resourceRepository.findAllBanRes(5, Arrays.asList(IDict.useFlag_STOPED, IDict.useFlag_ERROR), IDict.dataFlag_DEL);
    }

    @Override
    public List<ResourceVo> findAllRes() {
        List<ResourceVo> resVoList = new ArrayList<>();
        // 创建查询条件
        List<SearchFilter> filters = SearchFilter.parse();
        List<Resource> resList = resourceRepository.findAll(DynamicSpecifications.bySearchFilter(filters, Resource.class));
        if (!XaUtils.isEmpty(resList)) {
            for (Resource res : resList) {
                ResourceVo resVo = new ResourceVo();
                try {
                    BeanUtils.copyAllProperties(res, resVo);
                } catch (Exception e) {
                    log.error("对象转换失败，对象信息：" + JsonMapper.toJsonString(res), e);
                }
                // 获取资源对应的角色集合
                List<Role> roles = findRolesByResCode(res.getCode());
                resVo.setRoles(roles);
                resVoList.add(resVo);
            }
        }
        return resVoList;
    }

    @Override
    public List<Role> findRolesByResCode(String resCode) {
        return resourceRoleRepository.findRolesByResCode(resCode);
    }

    @Override
    public Resource findOneByRes(@NotNull ResourceDto resource) {
        ResourceTypeEnum typeEnum = ResourceTypeEnum.getEnumByName(resource.resType);
        if (typeEnum == null) {
            throw new BusinessException(ErrorCodeEnum.GL9999406);
        }
        List<SearchFilter> filters = SearchFilter.parse();
        SearchFilter parentCodeFilter = new SearchFilter("parentCode", SearchFilter.Operator.EQ, resource.parentCode);
        SearchFilter resTypeFilter = new SearchFilter("resType", SearchFilter.Operator.EQ, resource.resType);
        SearchFilter resUrlFilter = new SearchFilter("resUrl", SearchFilter.Operator.EQ, resource.resUrl);
        SearchFilter systemCodeFilter = new SearchFilter("systemCode", SearchFilter.Operator.EQ, resource.systemCode);
        if (5 == typeEnum.getLevel()) {
            SearchFilter resMethodFilter = new SearchFilter("resMethod", SearchFilter.Operator.EQ, resource.resMethod);
            filters.add(resMethodFilter);
        }
        Collections.addAll(filters, parentCodeFilter, resTypeFilter, resUrlFilter, systemCodeFilter);
        Optional<Resource> res = resourceRepository.findOne(DynamicSpecifications.bySearchFilter(filters, Resource.class));
        return res.orElse(null);
    }

    @Override
    public PageBean<ResourceVo> findResByCondition(Integer pageNum, Integer pageSize, String sort, String condition) {
        // 构建分页工厂
        PageBeanFactory pageBeanFactory = PageBeanFactory.getInstance();
        return null;
    }

    /**
     * Method description：添加资源信息
     *
     * @param resDto 资源对象
     * @return Resource
     */
    @Override
    @Transactional
    public Resource save(@NotNull ResourceDto resDto) {
        String resType = resDto.resType;
        String parentCode = resDto.parentCode;
        ResourceTypeEnum typeEnum = ResourceTypeEnum.getEnumByName(resType);
        if (typeEnum == null) {
            throw new BusinessException(ErrorCodeEnum.GL9999404);
        }
        if (ResourceTypeEnum.RESOURCE_PLATFORM != typeEnum && StringUtils.isBlank(parentCode)) {
            throw new BusinessException(ErrorCodeEnum.GL9999404);
        }
        // 判断资源是否存在
        Resource resource = findOneByRes(resDto);
        if (resource != null) {
            if (!IDict.dataFlag_OK.equals(resource.getDataFlag())) {
                log.info("资源信息已存在，已将删除状态改为正常状态，资源编码={}", resource.getCode());
                resource.setDataFlag(IDict.dataFlag_OK);
                return resourceRepository.save(resource);
            }
            if (!IDict.useFlag_USERED.equals(resource.getResFlag())) {
                throw new BusinessException(ErrorCodeEnum.GL99990005, resource.getResFlag());
            }
            if (!resDto.name.equals(resource.getName())) {
                throw new BusinessException(ErrorCodeEnum.GL9999408, resource.getName());
            }
            throw new BusinessException(ErrorCodeEnum.GL99990006);
        }
        Resource pres = null;
        if (StringUtils.isNotBlank(parentCode)) {
            // 获取父级资源
            Optional<Resource> res = resourceRepository.findByCode(Resource.class, parentCode);
            if (res.isPresent()) {
                pres = res.get();
            } else {
                throw new BusinessException(ErrorCodeEnum.GL9999405);
            }
        }
        // 生成资源编码
        String resCode = genResourceCode(pres, typeEnum);
        if (resCode == null) {
            throw new BusinessException(ErrorCodeEnum.GL9999411, JsonMapper.toJsonString(resDto));
        }
        // 创建资源
        Resource res = new Resource();
        res.setCode(resCode);
        res.setLevel(typeEnum.getLevel());
        try {
            BeanUtils.copyAllProperties(resDto, res);
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.GL99990004, JsonMapper.toJsonString(resDto), JsonMapper.toJsonString(res));
        }
        return resourceRepository.save(res);
    }


    /**
     * 生成菜单编码
     * 编码规则：
     * 1.平台编码(m00)
     * 2.系统编码(m00.00)
     * 3.目录编码(m00.00.00)
     * 4.菜单编码(m00.00.00.00)
     * 5.按钮编码(m00.00.00.00.00)
     *
     * @param pres 父级资源
     * @return 菜单编码
     */
    private String genResourceCode(Resource pres, ResourceTypeEnum resType) {
        String resCode;
        int presLevel = pres == null ? 0 : pres.getLevel();
        if (presLevel != resType.getLevel() - 1) { // resType与 pres不一致
            throw new BusinessException(ErrorCodeEnum.GL9999406);
        }
        if (pres == null) { // 一级资源
            // 获取所有的一级资源
            List<Resource> platformRes = findResByResType(resType, null);
            resCode = "m" + String.format("%02d", platformRes.size());
        } else if (StringUtils.isNotBlank(pres.getCode())) {
            // 获取同等级资源列表
            List<Resource> platformRes = findResByResType(resType, pres.getCode());
            resCode = pres.getCode() + Symbol.SPOT + String.format("%02d", platformRes.size());
        } else {
            throw new BusinessException(ErrorCodeEnum.GL9999410);
        }
        return resCode;
    }

    @Override
    public List<Resource> findResByResType(@NotNull ResourceTypeEnum resType, String parentCode) {
        return resourceRepository.findByResTypeAndParentCode(resType.getName(), parentCode);
    }

    public static void main(String[] args) {
        String format = String.format("%02d", 2);
        System.out.println(format);
    }
}
